package com.etooling.framework.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 修改时间 : 2025年1月28日
 * Redis 服务类，提供了对 Redis 数据库进行操作的常用方法。
 * 包括存储、获取、删除和检查数据是否存在等操作。
 * 1. void saveToRedis(String key, Object value, long timeout, TimeUnit timeUnit); 将数据存储到 Redis 中，并设置过期时间。
 * 2. void saveToRedis(String key, Object value); 将数据存储到 Redis 中，不设置过期时间。
 * 3. Object getFromRedis(String key); 从 Redis 中获取数据。
 * 4. boolean existsInRedis(String key); 检查指定的键是否存在于 Redis 中。
 * 5. void deleteFromRedis(String key); 从 Redis 中删除指定的键及其对应的值。
 * 6. void saveMultipleToRedis(Map<String, Object> keyValueMap); 批量将数据存储到 Redis 中。
 * 7. List<Object> getMultipleFromRedis(List<String> keys); 批量从 Redis 中获取数据。
 * 8. void deleteMultipleFromRedis(List<String> keys); 批量从 Redis 中删除数据。
 */
@Service
public class RedisService {

    // 日志记录器，用于记录日志信息
    private static final Logger logger = LoggerFactory.getLogger(RedisService.class);

    // 自动注入 RedisTemplate，用于与 Redis 进行交互
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 将数据存储到 Redis 中，并设置过期时间。
     *
     * @param key      存储在 Redis 中的键
     * @param value    存储在 Redis 中的值
     * @param timeout  过期时间
     * @param timeUnit 过期时间单位（如秒、分钟等）
     */
    public void saveToRedis(String key, Object value, long timeout, TimeUnit timeUnit) {
        try {
            // 使用 opsForValue() 方法获取 ValueOperations 对象，并调用 set 方法存储数据
            redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error saving data to Redis for key: {}", key, e);
        }
    }

    /**
     * 将数据存储到 Redis 中，不设置过期时间。
     *
     * @param key   存储在 Redis 中的键
     * @param value 存储在 Redis 中的值
     */
    public void saveToRedis(String key, Object value) {
        try {
            // 使用 opsForValue() 方法获取 ValueOperations 对象，并调用 set 方法存储数据
            redisTemplate.opsForValue().set(key, value);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error saving data to Redis for key: {}", key, e);
        }
    }

    /**
     * 从 Redis 中获取数据。
     *
     * @param key 存储在 Redis 中的键
     * @return 返回从 Redis 中获取的数据，如果不存在则返回 null
     */
    public Object getFromRedis(String key) {
        try {
            // 使用 opsForValue() 方法获取 ValueOperations 对象，并调用 get 方法获取数据
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error getting data from Redis for key: {}", key, e);
        }
        return null;
    }

    /**
     * 检查指定的键是否存在于 Redis 中。
     *
     * @param key 存储在 Redis 中的键
     * @return 如果键存在则返回 true，否则返回 false
     */
    public boolean existsInRedis(String key) {
        try {
            // 调用 hasKey 方法检查键是否存在
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error checking existence of key: {}", key, e);
        }
        return false;
    }

    /**
     * 从 Redis 中删除指定的键及其对应的值。
     *
     * @param key 存储在 Redis 中的键
     */
    public void deleteFromRedis(String key) {
        try {
            // 调用 delete 方法删除指定的键
            redisTemplate.delete(key);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error deleting data from Redis for key: {}", key, e);
        }
    }

    /**
     * 批量将数据存储到 Redis 中。
     *
     * @param keyValueMap 键值对映射，包含多个要存储的数据
     */
    public void saveMultipleToRedis(Map<String, Object> keyValueMap) {
        try {
            // 使用 opsForValue() 方法获取 ValueOperations 对象，并调用 multiSet 方法批量存储数据
            redisTemplate.opsForValue().multiSet(keyValueMap);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error saving multiple data to Redis", e);
        }
    }

    /**
     * 批量从 Redis 中获取数据。
     *
     * @param keys 需要获取数据的键列表
     * @return 返回从 Redis 中获取的数据列表，如果某个键不存在，则对应位置返回 null
     */
    public List<Object> getMultipleFromRedis(List<String> keys) {
        try {
            // 使用 opsForValue() 方法获取 ValueOperations 对象，并调用 multiGet 方法批量获取数据
            return redisTemplate.opsForValue().multiGet(keys);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error getting multiple data from Redis", e);
        }
        return null;
    }

    /**
     * 批量从 Redis 中删除数据。
     *
     * @param keys 需要删除的键列表
     */
    public void deleteMultipleFromRedis(List<String> keys) {
        try {
            // 调用 delete 方法批量删除指定的键
            redisTemplate.delete(keys);
        } catch (Exception e) {
            // 记录错误日志
            logger.error("Error deleting multiple data from Redis", e);
        }
    }
}